package com.swak.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.core.annotation.AliasFor;

import com.swak.loadbalance.LoadBalances;
import com.swak.utils.StringUtils;

/**
 * 定义定时任务
 * 
 * @author lifeng
 * @date 2021年2月25日 上午11:05:52
 */
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@FluxService
public @interface Job {

	/**
	 * 任务唯一值 如果是重试任务，则Id设置失效，指定id = 'RetryJob';
	 * 
	 * @return
	 */
	String id() default StringUtils.EMPTY;

	/**
	 * Spring 实例化的名称
	 * 
	 * @return
	 */
	@AliasFor(annotation = FluxService.class)
	String value() default StringUtils.EMPTY;

	/**
	 * 任务的中文描述
	 * 
	 * @return
	 */
	String name() default StringUtils.EMPTY;

	/**
	 * 任务执行时间表达式:
	 * 
	 * 秒（0-59）   , - * /   
	 * 分钟（0-59）  , - * /  
	 * 小时（0-23）  , - * / 
	 * 日（1-31）   , - * ? / L W C   
	 * 月（1-12 或 JAN-DEC） , - * /
	 * 星期几（1-7 或 SUN-SAT） , - * ? / L C #   
	 * 年（可选，1970-2099） , - * /
	 * 
	 * 举例：
	 * "0/10 * * * * *" 每10秒触发
	 * "0 15 10 ? * *" 每天上午10:15触发   
	 * "0 15 10 * * ?" 每天上午10:15触发   
	 * "0 15 10 * * ? *" 每天上午10:15触发   
	 * "0 15 10 * * ? 2005" 2005年的每天上午10:15触发   
	 * "0 * 14 * * ?" 在每天下午2点到下午2:59期间的每1分钟触发   
	 * "0 0/5 14 * * ?" 在每天下午2点到下午2:55期间的每5分钟触发   
	 * "0 0/5 14,18 * * ?" 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发   
	 * "0 0-5 14 * * ?" 在每天下午2点到下午2:05期间的每1分钟触发   
	 * "0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44触发   
	 * "0 15 10 ? * MON-FRI" 周一至周五的上午10:15触发   
	 * "0 15 10 15 * ?" 每月15日上午10:15触发   
	 * "0 15 10 L * ?" 每月最后一日的上午10:15触发   
	 * "0 15 10 ? * 6L" 每月的最后一个星期五上午10:15触发   
	 * "0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发  
	 * 
	 * @return
	 */
	String cronExpression() default StringUtils.EMPTY;

	/**
	 * 是否需要保证执行的顺序，如果需要则，会等此次调度执行完成之后才能发起下一下的调度 这个和并行模式不一样，并行模式的order
	 * 只能限制同一jvm实例中的顺序执行 是一个执行度的概念
	 * 
	 * @return
	 */
	boolean order() default false;

	/**
	 * 任务是否自动运行; 非自动运行的任务可以通过管理后台调度运行
	 * 
	 * @return
	 */
	boolean autorun() default true;

	/**
	 * 任务分发数量，如果没有定义分发的方法，则默认使用这个值来决定分发的数量 投递消息的数量
	 * 
	 * @return
	 */
	int dispatchTasks() default 1;

	/**
	 * 任务分发：dispatchMethod
	 * like dispatch(JobFragments fragments)
	 * 
	 * @return
	 */
	String dispatchMethod() default StringUtils.EMPTY;

	/**
	 * 任务执行：executeMethod
	 * 
	 * @return
	 */
	String executeMethod() default StringUtils.EMPTY;

	/**
	 * 任务分组： 进一步对任务细化： name:group
	 * 
	 * @return
	 */
	String group() default StringUtils.EMPTY;

	/**
	 * 负载均衡策略
	 * 
	 * @return
	 */
	LoadBalances loadBalance() default LoadBalances.WeightingRoundRobin;

	/**
	 * 执行器的权重: 任务分发时会投递给执行器，根据权重来决定投递的份额； 需配合 isolateExecute = true 才能生效
	 * 
	 * @return
	 */
	int weight() default 1;

	/**
	 * 执行器执行失败的重试次数
	 * 
	 * @return
	 */
	int retryTimes() default 3;

	/**
	 * 是否是重试任务: retryJob 如果是重试任务，则Id设置失效，指定id = 'RetryJob';
	 * 
	 * @return
	 */
	// boolean retryJob() default false;

	/**
	 * 是否隔离执行者，对执行者有效
	 * 
	 * @return
	 */
	boolean isolateExecute() default false;

	/**
	 * 是否开启
	 * 
	 * @return
	 */
	boolean opened() default true;

	/**
	 * 服务启动立即执行一次
	 * 
	 * @return
	 */
	boolean runOnBoot() default false;

	/**
	 * 定义执行的线程池：dispatchMethod, executeMethod, 和并行模式
	 * 
	 * @return
	 */
	@AliasFor(annotation = FluxService.class)
	Context context() default Context.Concurrent;

	/**
	 * 默认在统一的线程池中执行，每个执行者最多占用一半的线程
	 * 
	 * @return 可以设置在哪个 pool 中运行
	 */
	@AliasFor(annotation = FluxService.class)
	String pool() default StringUtils.EMPTY;

	/**
	 * 自定义了 pool，此参数才会生效
	 * 
	 * @return 定义线程池的线程数
	 */
	@AliasFor(annotation = FluxService.class)
	int workers() default 1;

	/**
	 * 最大并发：占用一半的线程来执行任务 这里和设置 context = Context.Order 效果一样
	 * 
	 * @return 发布服务的个数
	 */
	@AliasFor(annotation = FluxService.class)
	int parallel() default -1;
}
